package com.xlg.file.center.utils;

import com.xlg.file.center.handler.FileHandlerFactory;
import com.xlg.file.center.handler.Handler;
import com.xlg.file.center.handler.IFileHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author: 18310740596@163.com
 * @date: 2023-07-14 23:37:32
 * @version: v1.0
 * @describe: class responsibility
 */
@Slf4j
public class TaskHandler {
    private static final BlockingQueue<Task> OWNER_TASK_QUEUE = new ArrayBlockingQueue<>(50);

    private static volatile boolean isInitHandler = false;

    private static boolean writeTitle = false;

    private final Semaphore tokenBucket;

    private final Handler handler;

    private static final String FILE_PATH = System.getProperty("java.io.tmpdir");

    public TaskHandler(Semaphore tokenBucket) {
        init();
        this.tokenBucket = tokenBucket;
        this.handler = Handler.builder()
                .filePath(FILE_PATH)
                .msg(new StringBuffer())
                .fileLine(new AtomicInteger(0))
                .build();
    }

    public void registerTask(Task task) {
        boolean offer = OWNER_TASK_QUEUE.offer(task);
        if (!offer) {
            log.error("{} 批次号数据过多,自动取消数据.", task.getBatchNo());
        }
    }


    private void init() {
        if (!isInitHandler) {
            synchronized (TaskHandler.class) {
                if (!isInitHandler) {
                    CompletableFuture.runAsync(this::handler);
                    isInitHandler = true;
                }
            }
        }
    }

    private void handler() {
        while (true) {
            Task task = null;
            try {
                task = OWNER_TASK_QUEUE.take();

                handler.setTask(task);

                IFileHandler fileHandler = FileHandlerFactory.instance(task.getFileType());
                if (!writeTitle) {
                    fileHandler.writeTitle(handler);
                    writeTitle = true;
                }
                fileHandler.writeContent(handler);

                if (task.isLastBatch()) {
                    TaskUtil.handlerRemove(task.getUniqNo());
                    handlerResult(task);
                    tokenBucket.release();
                    break;
                }
            } catch (Exception e) {
                log.error("唯一批次号:{} 批次号:{} 任务处理失败", task.getUniqNo(), task.getBatchNo(), e);

                handler.getMsg()
                        .append(task.getUniqNo())
                        .append("批次号[")
                        .append(task.getBatchNo())
                        .append("] 数据写入失败,请检查")
                        .append(System.lineSeparator());

                handlerResult(task);
                tokenBucket.release();
            }
        }
    }

    private void handlerResult(Task task) {
        String msg = handler.getMsg().toString();
        ResultType resultType;
        if (StringUtils.isBlank(msg)) {
            resultType = ResultType.SUCCESS;
        } else {
            resultType = ResultType.FAILED;
        }

        TaskResult taskResult = TaskResult.builder()
                .batchNo(task.getBatchNo())
                .file(handler.getFile())
                .resultType(resultType)
                .msg(msg)
                .build();

        // 结果集填充
        TaskUtil.resultFill(task.getBatchNo()).complete(taskResult);
    }
}
